home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $RCSfile: UnMount.c,v $
- ** $Filename: UnMount.c $
- ** $Revision: 0.1 $
- ** $Date: 1995/04/29 17:33:51 $
- **
- ** Try to Shutdown or at least Inhibit DOS-Handlers (version 1.1)
- **
- ** (C) Copyright 1995-2002 by Etienne Vogt
- */
-
- #include <exec/alerts.h>
- #include <exec/memory.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <dos/filehandler.h>
- #include <workbench/startup.h>
- #define __USE_SYSBASE
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <clib/alib_protos.h>
- #include <string.h>
-
- struct ExecBase *SysBase;
- struct DosLibrary *DOSBase;
- static struct WBStartup *wbmsg;
- static struct RDArgs *myrda;
-
- static UBYTE version[] = "$VER: UnMount 1.1 (24.8.2002)";
- static UBYTE template[] = "DEVICE,INHIBIT/S,RETRY/K/N,ALL/S,FREENODE/S,QUIET/S";
-
- #define DBUFSIZE 16
- #define DNAMSIZE 24
-
- struct devBuffer
- { struct devBuffer *dbf_Link;
- UBYTE dbf_Name[DBUFSIZE][DNAMSIZE];
- };
-
- #define OPT_DEVICE 0
- #define OPT_INHIBIT 1
- #define OPT_RETRY 2
- #define OPT_ALL 3
- #define OPT_FREENODE 4
- #define OPT_QUIET 5
- #define OPTMAX 6
-
- ULONG __saveds main(void);
- static void cleanexit(ULONG rc);
- static int unmount(STRPTR device, int inhibit, int retry, int quiet);
- static struct devBuffer *getdevices(int *nodes);
- static void freedbufs(struct devBuffer *dbufs);
- static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet);
- static void freeNode(STRPTR device);
- static void freeWeird(BPTR bp, ULONG size);
-
- ULONG __saveds main(void) /* No startup code */
- {
- struct Process *myproc;
- LONG opts[OPTMAX];
- ULONG rc = 0;
-
- SysBase = *(struct ExecBase **)4;
- DOSBase = NULL;
- wbmsg = NULL;
- myrda = NULL;
-
- myproc = (struct Process *)FindTask(NULL);
- if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
- { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
- return 100;
- }
-
- if (!(myproc->pr_CLI)) /* If started from WB, exit cleanly */
- { WaitPort(&(myproc->pr_MsgPort));
- wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
- cleanexit(20);
- }
- else
- { APTR oldwinptr;
- int retrycount = 10, error;
-
- memset((char *)opts, 0, sizeof(opts));
- if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
- { PrintFault(IoErr(),"UnMount");
- cleanexit(20);
- }
-
- if (opts[OPT_RETRY]) retrycount = *((LONG *)opts[OPT_RETRY]);
-
- oldwinptr = myproc->pr_WindowPtr; /* Disable DOS Requesters */
- myproc->pr_WindowPtr = (APTR)(-1L);
-
- if (opts[OPT_DEVICE])
- { struct DosList *dol;
- char buffer[DNAMSIZE];
- STRPTR colon;
-
- dol = LockDosList(LDF_DEVICES | LDF_READ);
- strncpy(buffer, (STRPTR)opts[OPT_DEVICE], sizeof(buffer));
- if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
- else buffer[DNAMSIZE-1] = (UBYTE)0;
- if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
- { if (dol->dol_Task) /* There's a handler process running */
- { UnLockDosList(LDF_DEVICES | LDF_READ);
- if (error = unmount((STRPTR)opts[OPT_DEVICE], opts[OPT_INHIBIT], retrycount, opts[OPT_QUIET]))
- { PrintFault(error, "UnMount");
- rc = 10;
- }
- }
- else UnLockDosList(LDF_DEVICES | LDF_READ);
- if (opts[OPT_FREENODE]) freeNode((STRPTR)opts[OPT_DEVICE]);
- }
- else
- { UnLockDosList(LDF_DEVICES | LDF_READ);
- PrintFault(ERROR_DEVICE_NOT_MOUNTED, "UnMount");
- rc = 20;
- }
-
- }
- else if (opts[OPT_ALL])
- { struct devBuffer *dbuf;
- int numdevs;
-
- if (dbuf = getdevices(&numdevs)) killdevices(dbuf, numdevs, opts[OPT_INHIBIT], retrycount, opts[OPT_FREENODE], opts[OPT_QUIET]);
- else
- { PrintFault(ERROR_NO_FREE_STORE, "UnMount");
- rc = 20;
- }
- }
- else
- { PrintFault(ERROR_REQUIRED_ARG_MISSING, "UnMount");
- rc = 20;
- }
-
- myproc->pr_WindowPtr = oldwinptr;
- }
- cleanexit(rc);
- }
-
- static void cleanexit(ULONG rc)
- {
- if (myrda) FreeArgs(myrda);
- if (DOSBase) CloseLibrary((struct Library *)DOSBase);
- if (wbmsg)
- { Forbid();
- ReplyMsg((struct Message *)wbmsg);
- }
- Exit(rc);
- }
-
- static int unmount(STRPTR device, int inhibit, int retry, int quiet)
- { struct DevProc *dvp;
- int count = 0, rc = 0;
-
- if (!strchr(device,':')) return ERROR_INVALID_COMPONENT_NAME;
- if (dvp = GetDeviceProc(device, NULL))
- { if (DoPkt0(dvp->dvp_Port, ACTION_DIE) == DOSFALSE)
- { rc = IoErr();
- if (IsFileSystem(device) && inhibit)
- { if (!quiet) Printf("UnMount: Couldn't kill device %s, Trying to inhibit...\n", device);
- do
- { if (Inhibit(device, DOSTRUE)) break;
- else if ((rc = IoErr()) == ERROR_ACTION_NOT_KNOWN) count = retry;
- else Delay(TICKS_PER_SECOND);
- } while (++count < retry);
- if (count < retry) rc = 0;
- }
- }
- FreeDeviceProc(dvp);
- }
- else rc = IoErr();
- return rc;
- }
-
- static struct devBuffer *getdevices(int *nodes)
- { struct devBuffer *dbuf;
-
- if (dbuf = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
- { struct DosList *dol;
- struct devBuffer *db = dbuf;
- int i = 0;
-
- dol = LockDosList(LDF_DEVICES | LDF_READ);
- *nodes = 0;
- while (dol = NextDosEntry(dol, LDF_DEVICES))
- { UBYTE namlen;
- UBYTE *namptr;
-
- if (dol->dol_Task == NULL) continue;
- namptr = BADDR(dol->dol_Name);
- namlen = (namptr[0] < DNAMSIZE - 1 ? namptr[0] : DNAMSIZE - 2);
- strncpy(db->dbf_Name[i], namptr + 1, namlen);
- db->dbf_Name[i][namlen] = ':';
- db->dbf_Name[i][namlen+1] = '\0';
- if (strcmp(db->dbf_Name[i], "RAM:") == 0 || strcmp(db->dbf_Name[i], "ENV:") == 0) continue;
- (*nodes)++;
-
- if (++i == DBUFSIZE)
- { struct devBuffer *db1;
-
- if (db1 = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
- { db->dbf_Link = db1;
- db = db1;
- i = 0;
- }
- else
- { UnLockDosList(LDF_DEVICES | LDF_READ);
- freedbufs(dbuf);
- return NULL;
- }
- }
- }
- UnLockDosList(LDF_DEVICES | LDF_READ);
- }
- return dbuf;
- }
-
- static void freedbufs(struct devBuffer *dbufs)
- { struct devBuffer *nextdb;
-
- do
- { nextdb = dbufs->dbf_Link;
- FreeVec(dbufs);
- } while (dbufs = nextdb);
- }
-
- static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet)
- { struct devBuffer *db = dbuf;
- STRPTR devname;
- int j, i, error;
-
- for (j = 0, i = 0 ; j < numdevs ; j++)
- { devname = db->dbf_Name[i];
- if (IsFileSystem(devname))
- { if (!quiet) Printf("Unmounting device %s\n", db->dbf_Name[i]);
- if (error = unmount(devname, inhibit, retry, TRUE) && !quiet) PrintFault(error, "UnMount");
- else if (freenode) freeNode(devname);
- }
-
- if (++i == DBUFSIZE)
- { db = db->dbf_Link;
- i = 0;
- }
- }
- freedbufs(dbuf);
- }
-
- static void freeNode(STRPTR device)
- { struct DosList *dol;
- char buffer[DNAMSIZE];
- STRPTR colon;
- struct FileSysStartupMsg *fssm;
- struct DosEnvec *de;
-
- dol = LockDosList(LDF_DEVICES | LDF_WRITE);
- strncpy(buffer, device, sizeof(buffer));
- if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
- else buffer[DNAMSIZE-1] = (UBYTE)0;
- if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
- { RemDosEntry(dol);
- if (TypeOfMem(fssm = BADDR(dol->dol_misc.dol_handler.dol_Startup)) && ((ULONG)fssm & 1) == 0)
- { de = BADDR(fssm->fssm_Environ);
- /* and now for some extremely bizarre assumptions... */
- if (*(UBYTE *)fssm == 0 || *(UBYTE *)BADDR(fssm->fssm_Device) != 0
- && TypeOfMem(de) != 0 && (de->de_TableSize & 0xffffff00) == 0)
- { if (de->de_TableSize >= DE_CONTROL) freeWeird(de->de_Control, 0);
- freeWeird(fssm->fssm_Device, 0);
- freeWeird(fssm->fssm_Environ, (de->de_TableSize + 1) * sizeof(ULONG));
- freeWeird(dol->dol_misc.dol_handler.dol_Startup, sizeof(struct FileSysStartupMsg));
- }
- else freeWeird(dol->dol_misc.dol_handler.dol_Startup, 0); /* Probably a startup string */
- }
- freeWeird(dol->dol_misc.dol_handler.dol_Handler, 0);
- FreeDosEntry(dol);
- }
- UnLockDosList(LDF_DEVICES | LDF_WRITE);
- }
-
- /* From Ralph Babel's excellent Guru Book */
-
- static void freeWeird(BPTR bp, ULONG size)
- { UBYTE *p;
-
- if (bp)
- { p = BADDR(bp);
- if (TypeOfMem(p)) /* Should point to valid memory */
- { if (((ULONG)p & MEM_BLOCKMASK) == 0) FreeMem(p, size != 0 ? size : *p + 2);
- else FreeVec(p); /* Assume BCPL-style memory vector */
- }
- }
- }
-